#include<iostream>
#include<vector>
#include<algorithm>
#include<cassert>
#include<cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/eventfd.h>
#include <thread>
#include <mutex>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <functional>
#include <sys/epoll.h>
#include <unordered_map>
using namespace std;
#define BUFFER_SIZE 1024
class Buffer
{
    private:
    
    vector<char> _buffer;
    uint64_t _reader_idx;//读指针
    uint64_t _writer_idx;//写指针

    public:
    Buffer():_reader_idx(0),_writer_idx(0),_buffer(BUFFER_SIZE){}
    char* Begin(){return &*_buffer.begin();}//迭代器指针解引用为地址然后取地址返回
    char *WPosition(){return Begin()+_writer_idx;}
    char*RPosition(){return Begin()+_reader_idx;}
    uint64_t TailSize(){
       // cout<<_buffer.size()-_writer_idx<<endl;
        return _buffer.size()-_writer_idx;}//末尾空间大小-写偏移之后的空间大小
    uint64_t HeadSize(){return _reader_idx;}//开头空间大小-读偏移之前的空间大小
    uint64_t Readablesize(){return _writer_idx-_reader_idx;}//写入但还没读的大小
    void MoveReadOffset(uint64_t len){
        assert(len<=Readablesize());
      _reader_idx=  _reader_idx+len;
    //  cout<<"radix:"<<_reader_idx<<endl;
    }//读指针可以向后移动一段距离
    void MoveWriteOffset(uint64_t len){
        assert(len<=TailSize());
      //  cout<<"?????????"<<endl;
       _writer_idx= _writer_idx+len;
      //  cout<<_writer_idx<<endl;
    }//写指针可以向后移动一段距离
    void EnsureWriteSpace(uint64_t len)
    {
        if(TailSize()>=len){return ;}
        else if(TailSize()+HeadSize()>=len)//末尾空间大小加上开头空间大小装得下的话把先前的部分挪到前面
        {
            uint64_t hnr= Readablesize();
            copy(RPosition(),RPosition()+hnr,Begin());
            _reader_idx=0;
            _writer_idx=hnr;
        }else{//空间不够就扩容
        _buffer.resize(_writer_idx+len);
        }
    }

    void Write(const void*data,uint64_t len)//把数据写入buffer
    {
        //有足够空间，拷贝数据进去
        if(len==0) return ;//没数据
        
        EnsureWriteSpace(len);//保证有足够空间
        const char* d=(const char*)data;
        copy(d,d+len,WPosition());

    }
    void Writeandpush(const void*data,uint64_t len)
    {
        Write(data,len);
        MoveWriteOffset(len);
    }

    void WriteString(const string&data)
    {
        Write(data.c_str(),data.size());//data.c_str//()类型是const char* 
    }

    void  WriteStringandPush(const string&data)
    {
        Write(data.c_str(),data.size());//data.c_str//()类型是const char* 
     //   cout<<data<<": "<<data.size()<<endl;
         MoveWriteOffset(data.size());
      //   cout<<Readablesize()<<endl;
    }

    void WriteBuffer(Buffer&data)
    {
        Write(data.RPosition(),data.Readablesize());//把参数的已经写入但还没读的数据写入当前缓冲区中
    }

     void WriteBufferandpush(Buffer&data)
     {
        Write(data.RPosition(),data.Readablesize());//把参数的已经写入但还没读的数据写入当前缓冲区中
        MoveWriteOffset(data.Readablesize());
     }

     void Read(void*buff,uint64_t len)//把已经写入但还没读的数据读出
     {
        assert(len<=Readablesize());
        //cout<<"::::::::::"<<endl;
        copy(RPosition(),RPosition()+len,(char*)buff);
    //    cout<<"+++++++++++"<<endl;
     }
     void ReadandPop(void* buff,uint64_t len)
     {
        Read(buff,len);
        MoveReadOffset(len);
     //   cout<<"<<<<<<<<<<"<<endl;
     }
     string ReadAsstring(uint64_t len)//读一行
     {
        assert(Readablesize()>=len);
       std:: string strs;
        strs.resize(len);
        Read(&strs[0],len);//str[0]类型是const char*
        return strs;
     }
     char*FindCRLF()//找换行符
     {
        char*res=(char*)memchr((void*)RPosition(),'\n',Readablesize());//在已经写入但还没读的数据读到换行符的位置
        return res;//如果没有换行符则返回null
     }
     string Getline()
     {
        char*pos=FindCRLF();
        if(pos==NULL) return "";
        return ReadAsstring(pos-RPosition()+1);//+1是为了把\n读出
     }
     string Getlineandpop()
     {
        string str=Getline();
        MoveReadOffset(str.size());
        return str;
     }

     void clear()//清空缓冲区
     {
        _reader_idx=0;
        _writer_idx=0;
     }
};

#define MAX_LISTEN 1024
#define IPPROTO_TCp 0
#define INF 0
#define DBG 1
#define ERR 2
#define LOG_LEVEL DBG
//\是续航符time是时间函数，strftime把时间格式化为一个时间字符串;如果传递的level大于LOG_LEVEL就打印
#define LOG(level,format,...) do{\
    if(level<LOG_LEVEL) break;\
    time_t t=time(NULL);\
    struct tm*ltm=localtime(&t);\
    char tmp[31]={0};\
    strftime(tmp,31,"%H:%M:%S",ltm);\
fprintf(stdout,"[%s %s:%d] ",format "\n",tmp,__FILE__,__LINE__,##__VA_ARGS__);\
}while(0)
//stdout是FILE*类型表示输出的文件流，"%s:%d"是格式化字符串，__FILE__和__LINE__是预定义的宏，表示当前文件名和行号
#define INT_LOG(format,...) LOG(INF,format,##__VA_ARGS__)
#define DBG_LOG(format,...) LOG(DBG,format,##__VA_ARGS__)
#define ERR_LOG(format,...) LOG(ERR,format,##__VA_ARGS__)

class   NetWork{

public:


};

class Socket{

private:
int _sockfd;

public:
Socket():_sockfd(-1){}
Socket(int fd):_sockfd(fd){}
~Socket(){Close();}
int Getfd(){return _sockfd;}
void Close()
{
    if(_sockfd!=-1)
    {
        close(_sockfd);
        _sockfd=-1;
    }
}

bool Create()
{
    _sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCp);
    if(_sockfd<0)
    {
        ERR_LOG("create socket failed");
        return false;
    }
    return true; 
}
bool Bind(const std::string &ip,uint16_t port)
{
    struct sockaddr_in addr;
    addr.sin_family=AF_INET;
    addr.sin_port=htons(port);
    addr.sin_addr.s_addr=inet_addr(ip.c_str());
    if(bind(_sockfd,(struct sockaddr*)&addr,sizeof(addr))<0)
    {
        ERR_LOG("bind socket failed");
        return false;
    }
    return true;
}
bool Listen(int backlog=MAX_LISTEN)
{
    if(listen(_sockfd,backlog)<0)
    {
        ERR_LOG("listen socket failed");
        return false;
    }
    return true;
}
bool Connect(const std::string &ip,uint16_t port)
{
    struct sockaddr_in addr;
    addr.sin_family=AF_INET;
    addr.sin_port=htons(port);
    addr.sin_addr.s_addr=inet_addr(ip.c_str());
    if(connect(_sockfd,(struct sockaddr*)&addr,sizeof(addr))<0)
    {
        ERR_LOG("connect socket failed");
        return false;
    }
    return true;
}

int Accept()
{

    int newfd=accept(_sockfd,NULL,NULL);
    if(newfd<0)
    {
        ERR_LOG("accept socket failed");
        return -1;
    }
    return newfd;
}
///接受数据
ssize_t Rev(void*buff,size_t len,int flag=0)
{
    ssize_t ret=recv(_sockfd,buff,len,flag);
    //EAGAIN 当前socket的接收缓冲区中没有数据了，在⾮阻塞的情况下才会有这
    //EINTR 表⽰当前socket的阻塞等待，被信号打断了，
    if(ret<=0)
    {
        if(errno==EAGAIN||errno==EINTR)
        {
            return 0;
        }
        else
        {
            ERR_LOG("recv data failed");
            return -1;
        }
    }
    return ret;
}

ssize_t NonBlockRecv(void* buf,size_t len)//MSG_DONTWAIT表示当前接收为非阻塞
{
    return Rev(buf,len,MSG_DONTWAIT);
}
//发送数据
ssize_t Send(const void* buf,size_t len,int flag=0)//flag默认为0
{
    ssize_t ret=send(_sockfd,buf,len,flag);//往sockfd发送数据
    if(ret<0)
    {
        if(errno==EAGAIN||errno==EINTR)
        {
            return 0;
        }
        else
        {
            ERR_LOG("send data failed");
            return -1;
        }
    }
    return ret;//返回实际发送的字节数
}
ssize_t NonBlockSend(const void* buf,size_t len)
{
    return Send(buf,len,MSG_DONTWAIT);// MSG_DONTWAIT 表⽰当前发送为⾮阻塞
}

bool CreateServer(uint16_t port,const std::string &ip="0.0.0.0",bool block_flag=false)
{
    //1. 创建套接字，2. 绑定地址，3. 开始监听，4. 设置⾮阻塞， 5. 启动地址重⽤
    if(!Create())
    {
        return false;
    }
    
    if(!Bind(ip,port))
    {
        return false;
    }
      if(!Listen())
    {
        return false;
    }
    if(block_flag)NonBlock();//设置为非阻塞
  ReuseAddress();//设置套接字选项---开启地址端⼝重⽤
    return true;
}

bool CreateClient(uint16_t port,const std::string &ip,bool block_flag=false)
{
    if(!Create())
    {
        return false;
    }
    if(block_flag)NonBlock();//设置为非阻塞
    ReuseAddress();//设置套接字选项---开启地址端⼝重⽤
    if(!Connect(ip,port))
    {
        return false;
    }
    return true;
}   

void ReuseAddress()
{
    int val=1;
    setsockopt(_sockfd,SOL_SOCKET,SO_REUSEADDR,(void*)&val,sizeof(int));//允许重用本地地址和端口
    val=1;
    setsockopt(_sockfd,SOL_SOCKET,SO_REUSEPORT,(void*)&val,sizeof(int));//许多个套接字同时绑定到同一个IP地址和端口号上，而不会导致绑定冲突
    
}

void NonBlock(){
    int flag=fcntl(_sockfd,F_GETFL,0);//使用F_GETFL命令可以获取或设置文件的状态标志
    fcntl(_sockfd,F_SETFL,flag|O_NONBLOCK);//吧当前套接字设置为非阻塞
}

};

class Poller;
class EventLoop;
class Channel{
private:
uint32_t _events;//当前需要监控的事件
uint32_t _revents;//当前链接触发的事件
EventLoop *_EventLoop;//当前链接所属的eventloop
int _fd;//当前链接的文件描述符
using EventCallback=std::function<void()>;//回调函数
Poller *_poller;//poller指针
EventCallback _read_callback;//读事件回调函数
EventCallback _write_callback;//写事件回调函数
EventCallback _error_callback;//错误事件回调函数
EventCallback _close_callback;//关闭事件回调函数
EventCallback _event_callback;//事件回调函数

public:
Channel(EventLoop*evp, int fd):_fd(fd),_events(0),_revents(0),_EventLoop(evp){}
~Channel(){}
int Fd(){return _fd;}
uint32_t Events(){return _events;}
void SetRevents(uint32_t events){_revents=events;}//设置就绪事件
void SetReadCallback(const EventCallback &cb){_read_callback=cb;}
void SetWriteCallback(const EventCallback &cb){_write_callback=cb;}
void SetErrorCallback(const EventCallback &cb){_error_callback=cb;}
void SetCloseCallback(const EventCallback &cb){_close_callback=cb;}
void SetEventCallback(const EventCallback &cb){_event_callback=cb;}

bool ReadAble(){return _revents&EPOLLIN;}//判断是否有读事件
bool WriteAble(){return _revents&EPOLLOUT;}//判断是否有写事件

void EnableRead(bool flag=true){_events|=EPOLLIN;Update();}//设置读事件
void EnableWrite(bool flag=true){_events|=EPOLLOUT;Update();}//设置写事件

void DisableRead(){_events&=~EPOLLIN;Update();}//取消读事件
void DisableWrite(){_events&=~EPOLLOUT;Update();}//取消写事件

void DisableAll(){_events=0;Update();}//取消所有事件
void Remove();//移除事件后面调用eventloop
void Update();//更新事件
void HandleEvent(){
    if((_revents&EPOLLHUP)||(_revents&EPOLLIN)||(_revents&EPOLLPRI))//对方关闭连接,有数据可读，有紧急数据可读
    { if(_event_callback)_event_callback();//不管什么事件都调用这个函数
        if(_read_callback)_read_callback();
        
    }
    if(_revents&EPOLLOUT)//有数据可写
    { if(_event_callback)_event_callback();//不管什么事件都调用这个函数
        if(_write_callback)_write_callback();
        
    }
    else if(_revents&EPOLLERR)//错误事件
    {
        if(_error_callback)_error_callback();
    }
   else if(_revents&EPOLLRDHUP)//对方关闭连接
    {
        if(_close_callback)_close_callback();
    }
   
    
}//事件处理函数


};

#define MAX_EPOLLEVENTS 1024
class Poller{   
private:
int _epfd;
struct epoll_event _events[MAX_EPOLLEVENTS];
std::unordered_map<int,Channel*> _channels;
private:
void update(Channel*channel,int op)
{
    int fd=channel->Fd();
    struct epoll_event ev;
    ev.data.fd=fd;
    ev.events=channel->Events();
   int ret= epoll_ctl(_epfd,op,fd,&ev);
   if(ret<0){
    ERR_LOG("epoll_ctl failed");
   }
   return;
}
//判断channel是否添加了监控(添加进hash表)
bool hasChannel(Channel*channel)
{
    auto it=_channels.find(channel->Fd());
    return it!=_channels.end();
}
public:
Poller()
{
    _epfd=epoll_create(MAX_EPOLLEVENTS);
    if(_epfd<0)
    {
        ERR_LOG("epoll_create failed");
        abort();
    }
}

//添加或修改channel
void updateEvent(Channel*Channel)
{
    if(!hasChannel(Channel))//真-在->更新
    {//不在就添加
        _channels[Channel->Fd()]=Channel;
        update(Channel,EPOLL_CTL_ADD);
    }
    else
    {
        update(Channel,EPOLL_CTL_MOD);
    }
}

void RemoveEvent(Channel*channel)//移除channel出hash表
{
    if(!hasChannel(channel)) return ;
    update(channel,EPOLL_CTL_DEL);
    _channels.erase(channel->Fd());
}

void Poll(std::vector<Channel*>*active)
{
    cout<<"befoe epoll_wait"<<endl;
    int nfd=epoll_wait(_epfd,_events,MAX_EPOLLEVENTS,-1);
    //阻塞等待活跃事件第一个是监控的fd，第二个是事件数组的指针，第三个是事件的个数，第四个是等待的事件-1表示阻塞等待
cout<<"after epoll_wait"<<endl;
    if(nfd<0)
{
    if(errno==EINTR) return ;
    ERR_LOG("epoll_wait failed");
    abort();    
}
for(int i=0;i<nfd;i++)//遍历活跃事件，尾插进vcetor active
{
   
    auto it=_channels.find(_events[i].data.fd);
    assert(it!=_channels.end());
    it->second->SetRevents(_events[i].events);
    active->push_back(it->second);//添加进vector active活跃事件集中
}
return;
}
};



class EventLoop{
private:
using Functor=std::function<void()>;
std::thread::id _thread_id;
int _event_fd;//用于唤醒IO事件可能引起的队列任务阻塞
Poller _poller;
std::vector<Functor> _task;//任务队列
std::mutex _mutex;//互斥锁
Channel* _event_channel; // 添加 _event_channel 成员

public:
void RunAllTask(){
    std::vector<Functor> functor;
    {
        std::unique_lock<std::mutex> _lock(_mutex);//加锁，让后面的task内的任务交换到functor中是线程安全的
        _task.swap(functor);//task中的任务交换到functor中
    }
    for(auto &t:functor)//执行functor中的任务
    {
        t();
    }
}
static int CreateEventFd( ) {
    int evtfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if (evtfd < 0) {
        ERR_LOG("Failed to create eventfd");
        abort();
    }
    return evtfd;
}
static void ReadEventFd(int fd)
{
    uint64_t one=0;
    int n= read(fd,&one,sizeof(one));//读取eventfd
    if(n<0)
    {
        if(errno==EAGAIN||errno==EINTR) return ;
        ERR_LOG("read eventfd failed");
        abort();
    }
    return;
}

void WeakUpEventFd()
{
    uint64_t one=1;
    int n=write(_event_fd,&one,sizeof(one));//写入eventfd
    if(n<0)
    {
        if(errno==EAGAIN||errno==EINTR) return ;
        ERR_LOG("write eventfd failed");
        abort();
    }
    return;
}

public:
EventLoop():_thread_id(std::this_thread::get_id())
,_event_fd(CreateEventFd())
,_event_channel(new Channel(this, _event_fd))
{
    _event_channel->SetReadCallback(std::bind(ReadEventFd,_event_fd));
    _event_channel->EnableRead();
} 


void start()//事件监控-》就绪事件处理-》执行任务
{
    while(1){
    std::vector<Channel*> active;
    cout<<" std::vector<Channel*> active;"<<endl;
   _poller.Poll(&active);
   cout<<" _poller.Poll(&active);"<<endl;
   for(auto &it:active)
   {
       it->HandleEvent();
       cout<<"有一个事件"<<endl;
   }
    RunAllTask();//执行活跃事件执行完后执行任务队列
    cout<<" RunAllTask()"<<endl;
}
}
bool IsInLoopThread(){return _thread_id==std::this_thread::get_id();}//判断当前线程是否是对应eventloop的线程
void RuninLoop(const Functor&cb)//判断要执行的任务是否在当前线程，如果是就直接执行，不是就加入任务队列
{
    if(IsInLoopThread())
    {
        cb();
    }
    else
    {
        QueueInLoop(cb);
    }
}
void QueueInLoop(const Functor&cb)//任务加入线程池
{
    {
        std::unique_lock<std::mutex> _lock(_mutex);
        _task.push_back(cb);
    }
}
void UpdateEvent(Channel*channel){_poller.updateEvent(channel);}//添加或修改描述符的事件监控
void RemoveEvent(Channel*channel){_poller.RemoveEvent(channel);}//移除描述符的事件监控
void AssertInLoopThread(){assert(IsInLoopThread());}//断言当前线程是否是对应eventloop的线程

};

void Channel::Remove(){return _EventLoop->UpdateEvent(this);}//移除事件后面调用eventloop
void Channel::Update(){return _EventLoop->RemoveEvent(this);}//更新事件